package
{
	import aerys.minko.render.Viewport3D;
	import aerys.minko.scene.IScene3D;
	import aerys.minko.scene.Model3D;
	import aerys.minko.scene.camera.ArcBallCamera3D;
	import aerys.minko.scene.group.DepthSortGroup3D;
	import aerys.minko.scene.group.Group3D;
	import aerys.minko.scene.group.IGroup3D;
	import aerys.minko.scene.material.IMaterial3D;
	import aerys.minko.scene.material.SolidMaterial3D;
	import aerys.minko.scene.material.modifier.WireframeMaterial3D;
	import aerys.minko.scene.mesh.IMesh3D;
	import aerys.minko.scene.mesh.primitive.CubeMesh;
	import aerys.minko.scene.stardust.MinkoParticleInitializer;
	import aerys.minko.scene.stardust.ParticleEmitter3D;
	
	import flash.display.Sprite;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.system.System;
	import flash.ui.Keyboard;
	
	import idv.cjcat.stardust.common.clocks.ImpulseClock;
	import idv.cjcat.stardust.common.initializers.CollisionRadius;
	import idv.cjcat.stardust.common.initializers.Mass;
	import idv.cjcat.stardust.common.initializers.Scale;
	import idv.cjcat.stardust.common.math.UniformRandom;
	import idv.cjcat.stardust.threeD.actions.Collide3D;
	import idv.cjcat.stardust.threeD.actions.Deflect3D;
	import idv.cjcat.stardust.threeD.actions.Move3D;
	import idv.cjcat.stardust.threeD.actions.Oriented3D;
	import idv.cjcat.stardust.threeD.deflectors.BoundingCube;
	import idv.cjcat.stardust.threeD.emitters.Emitter3D;
	import idv.cjcat.stardust.threeD.initializers.Position3D;
	import idv.cjcat.stardust.threeD.initializers.Velocity3D;
	import idv.cjcat.stardust.threeD.zones.CubeZone;
	import idv.cjcat.stardust.threeD.zones.SphereZone;
	
	[SWF(backgroundColor=0,width=640,height=340)]
	
	public class Cubes extends Sprite
	{
		private static const MATERIAL	: IMaterial3D	= new WireframeMaterial3D(0x9900ffff,
																				  new SolidMaterial3D(0x5500ff00));
		private static const MESH		: IMesh3D		= CubeMesh.cubeMesh;
		private static const PARTICLE	: IScene3D		= new Model3D(MESH, MATERIAL)
		
		private var _vp			: Viewport3D		= null;
		private var _camera		: ArcBallCamera3D	= new ArcBallCamera3D();
		private var _scene		: IGroup3D			= new Group3D(_camera);
		
		public function Cubes()
		{
			initializeScene();
			initializeParticles();
		}
		
		private function enterFrameHandler(event : Event) : void
		{
			_camera.rotation.y += .05;
			if (_camera.distance > 110.)
				_camera.distance = 110.;
			
			_vp.render(_scene);
		}
		
		private function initializeScene() : void
		{
			_vp = Viewport3D.setupOnStage(stage);
			addChild(_vp);

			_camera.distance = 110.;
			
			stage.quality = StageQuality.MEDIUM;
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}
		
		private function initializeParticles() : void
		{
			var particles	: Group3D		= new DepthSortGroup3D();
			var clock		: ImpulseClock	= new ImpulseClock(42);
			var emitter 	: Emitter3D		= new Emitter3D(clock);
			var sphereZone	: SphereZone 	= new SphereZone(0, 0, 0, 1);
			var cubeZone	: CubeZone 		= new CubeZone(-32, -32, -32,
														   64, 64, 64);
			
			clock.impulse();
			
			//initializers
			emitter.addInitializer(new MinkoParticleInitializer(PARTICLE));
			
			emitter.addInitializer(new Position3D(cubeZone));
			emitter.addInitializer(new Velocity3D(sphereZone));
			emitter.addInitializer(new Scale(new UniformRandom(2.5, .5)));
			emitter.addInitializer(new CollisionRadius(.75));
			emitter.addInitializer(new Mass(new UniformRandom(1, 0)));
		
			//actions
			var deflect : Deflect3D = new Deflect3D();
			
			deflect.addDeflector(new BoundingCube(-32, -32, -32,
												  64, 64, 64));
			emitter.addAction(deflect);
			emitter.addAction(new Move3D());
			emitter.addAction(new Oriented3D(0.75));
			emitter.addAction(new Collide3D());
			
			particles.addChild(new ParticleEmitter3D(emitter));
			_scene.addChild(particles);
		}
		
		private function mouseWheelHandler(event : MouseEvent) : void
		{
			_camera.distance += -event.delta;
		}
		
		private function keyDownHandler(event : KeyboardEvent) : void
		{
			switch (event.keyCode)
			{
				case Keyboard.PAGE_UP :
					_camera.distance -= 5.;
					break ;
				case Keyboard.PAGE_DOWN :
					_camera.distance += 5.;
					break ;
			}
		}
	}
}